Micron Document
🎖️GitЯра🎖️


Displaying Raw • Download

core/data/src/commonMain/kotlin/org/meshtastic/core/data/manager/NodeManagerImpl.kt cdeb1ac532b587f5db718504b5d6093ab55a859c (cdeb1ac5) Text, 14.95 KB

T8b949e/*
* Copyright (c) 2025-2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.core.data.manager

Tff7b72import T7ee787co.touchlab.kermit.Logger
Tff7b72import T7ee787kotlinx.atomicfu.atomic
Tff7b72import T7ee787kotlinx.atomicfu.update
Tff7b72import T7ee787kotlinx.collections.immutable.persistentMapOf
Tff7b72import T7ee787kotlinx.coroutines.CoroutineScope
Tff7b72import T7ee787kotlinx.coroutines.flow.MutableStateFlow
Tff7b72import T7ee787kotlinx.coroutines.flow.first
Tff7b72import T7ee787okio.ByteString
Tff7b72import T7ee787org.koin.core.annotation.Named
Tff7b72import T7ee787org.koin.core.annotation.Single
Tff7b72import T7ee787org.meshtastic.core.common.util.handledLaunch
Tff7b72import T7ee787org.meshtastic.core.model.DataPacket
Tff7b72import T7ee787org.meshtastic.core.model.DeviceMetrics
Tff7b72import T7ee787org.meshtastic.core.model.EnvironmentMetrics
Tff7b72import T7ee787org.meshtastic.core.model.MeshUser
Tff7b72import T7ee787org.meshtastic.core.model.MyNodeInfo
Tff7b72import T7ee787org.meshtastic.core.model.Node
Tff7b72import T7ee787org.meshtastic.core.model.NodeInfo
Tff7b72import T7ee787org.meshtastic.core.model.Position
Tff7b72import T7ee787org.meshtastic.core.model.util.NodeIdLookup
Tff7b72import T7ee787org.meshtastic.core.repository.NodeManager
Tff7b72import T7ee787org.meshtastic.core.repository.NodeRepository
Tff7b72import T7ee787org.meshtastic.core.repository.Notification
Tff7b72import T7ee787org.meshtastic.core.repository.NotificationManager
Tff7b72import T7ee787org.meshtastic.core.repository.ServiceBroadcasts
Tff7b72import T7ee787org.meshtastic.core.resources.Res
Tff7b72import T7ee787org.meshtastic.core.resources.getStringSuspend
Tff7b72import T7ee787org.meshtastic.core.resources.new_node_seen
Tff7b72import T7ee787org.meshtastic.proto.DeviceMetadata
Tff7b72import T7ee787org.meshtastic.proto.HardwareModel
Tff7b72import T7ee787org.meshtastic.proto.Paxcount
Tff7b72import T7ee787org.meshtastic.proto.StatusMessage
Tff7b72import T7ee787org.meshtastic.proto.Telemetry
Tff7b72import T7ee787org.meshtastic.proto.User
Tff7b72import T7ee787org.meshtastic.proto.NodeInfo Tff7b72as Te6edf3ProtoNodeInfo
Tff7b72import T7ee787org.meshtastic.proto.Position Tff7b72as Te6edf3ProtoPosition

T8b949e/** Implementation of [NodeManager] that maintains an in-memory database of the mesh. */
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffLongParameterListTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffTooManyFunctionsTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffCyclomaticComplexMethodTa5d6ff"Tb4b4b4)
Tf0883e@SingleTb4b4b4(Te6edf3binds Tff7b72= Tff7b72[Te6edf3NodeManagerTff7b72::Te6edf3classTb4b4b4, Te6edf3NodeIdLookupTff7b72::Te6edf3classTff7b72]Tb4b4b4)
Tff7b72class T56d364NodeManagerImplTb4b4b4(
Tff7b72private Tff7b72val Te6edf3nodeRepositoryTb4b4b4: Te6edf3NodeRepositoryTb4b4b4,
Tff7b72private Tff7b72val Te6edf3serviceBroadcastsTb4b4b4: Te6edf3ServiceBroadcastsTb4b4b4,
Tff7b72private Tff7b72val Te6edf3notificationManagerTb4b4b4: Te6edf3NotificationManagerTb4b4b4,
Tf0883e@NamedTb4b4b4(Ta5d6ff"Ta5d6ffServiceScopeTa5d6ff"Tb4b4b4) Tff7b72private Tff7b72val Te6edf3scopeTb4b4b4: Te6edf3CoroutineScopeTb4b4b4,
Tb4b4b4) Tb4b4b4: Te6edf3NodeManager Tb4b4b4{

Tff7b72private Tff7b72val Te6edf3_nodeDBbyNodeNum Tff7b72= Te6edf3atomicTb4b4b4(Te6edf3persistentMapOfTff7b72<Tffa657IntTb4b4b4, Te6edf3NodeTff7b72>Tb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72private Tff7b72val Te6edf3_nodeDBbyID Tff7b72= Te6edf3atomicTb4b4b4(Te6edf3persistentMapOfTff7b72<Tffa657StringTb4b4b4, Te6edf3NodeTff7b72>Tb4b4b4(Tb4b4b4)Tb4b4b4)

Tff7b72override Tff7b72val Te6edf3nodeDBbyNodeNumTb4b4b4: Te6edf3MapTff7b72<Tffa657IntTb4b4b4, Te6edf3NodeTff7b72>
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3_nodeDBbyNodeNumTb4b4b4.Te6edf3value

Tff7b72override Tff7b72val Te6edf3nodeDBbyIDTb4b4b4: Te6edf3MapTff7b72<Tffa657StringTb4b4b4, Te6edf3NodeTff7b72>
Tff7b72getTb4b4b4(Tb4b4b4) Tff7b72= Te6edf3_nodeDBbyIDTb4b4b4.Te6edf3value

Tff7b72override Tff7b72val Te6edf3isNodeDbReady Tff7b72= Te6edf3MutableStateFlowTb4b4b4(Tff7b72falseTb4b4b4)
Tff7b72override Tff7b72val Te6edf3allowNodeDbWrites Tff7b72= Te6edf3MutableStateFlowTb4b4b4(Tff7b72falseTb4b4b4)

Tff7b72override Tff7b72fun Td2a8ffsetNodeDbReadyTb4b4b4(Te6edf3readyTb4b4b4: Tffa657BooleanTb4b4b4) Tb4b4b4{
Te6edf3isNodeDbReadyTb4b4b4.Te6edf3value Tff7b72= Te6edf3ready
Tb4b4b4}

Tff7b72override Tff7b72fun Td2a8ffsetAllowNodeDbWritesTb4b4b4(Te6edf3allowedTb4b4b4: Tffa657BooleanTb4b4b4) Tb4b4b4{
Te6edf3allowNodeDbWritesTb4b4b4.Te6edf3value Tff7b72= Te6edf3allowed
Tb4b4b4}

Tff7b72override Tff7b72val Te6edf3myNodeNum Tff7b72= Te6edf3MutableStateFlowTff7b72<Tffa657Int?Tff7b72>Tb4b4b4(Tff7b72nullTb4b4b4)

Tff7b72override Tff7b72fun Td2a8ffsetMyNodeNumTb4b4b4(Te6edf3numTb4b4b4: Tffa657Int?Tb4b4b4) Tb4b4b4{
Te6edf3myNodeNumTb4b4b4.Te6edf3value Tff7b72= Te6edf3num
Tb4b4b4}

Tff7b72companion Tff7b72object Tb4b4b4{
Tff7b72private Tff7b72const Tff7b72val Te6edf3TIME_MS_TO_S Tff7b72= T79c0ff1T79c0ff0T79c0ff0T79c0ff0L
Tb4b4b4}

Tff7b72override Tff7b72fun Td2a8ffloadCachedNodeDBTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3scopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{
Tff7b72val Te6edf3nodes Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3nodeDBbyNumTb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)
Te6edf3_nodeDBbyNodeNumTb4b4b4.Te6edf3value Tff7b72= Te6edf3persistentMapOfTff7b72<Tffa657IntTb4b4b4, Te6edf3NodeTff7b72>Tb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3putAllTb4b4b4(Te6edf3nodesTb4b4b4)
Tff7b72val Te6edf3byId Tff7b72= Te6edf3mutableMapOfTff7b72<Tffa657StringTb4b4b4, Te6edf3NodeTff7b72>Tb4b4b4(Tb4b4b4)
Te6edf3nodesTb4b4b4.Te6edf3valuesTb4b4b4.Te6edf3forEach Tb4b4b4{ Te6edf3byIdTff7b72[Tffa657itTb4b4b4.Te6edf3userTb4b4b4.Te6edf3idTff7b72] Tff7b72= Tffa657it Tb4b4b4}
Te6edf3_nodeDBbyIDTb4b4b4.Te6edf3value Tff7b72= Te6edf3persistentMapOfTff7b72<Tffa657StringTb4b4b4, Te6edf3NodeTff7b72>Tb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3putAllTb4b4b4(Te6edf3byIdTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3myNodeNumTb4b4b4.Te6edf3value Tff7b72=Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3myNodeNumTb4b4b4.Te6edf3value Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3myNodeInfoTb4b4b4.Te6edf3valueTff7b72?.Te6edf3myNodeNum
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Tff7b72override Tff7b72fun Td2a8ffclearTb4b4b4(Tb4b4b4) Tb4b4b4{
Te6edf3_nodeDBbyNodeNumTb4b4b4.Te6edf3value Tff7b72= Te6edf3persistentMapOfTb4b4b4(Tb4b4b4)
Te6edf3_nodeDBbyIDTb4b4b4.Te6edf3value Tff7b72= Te6edf3persistentMapOfTb4b4b4(Tb4b4b4)
Te6edf3isNodeDbReadyTb4b4b4.Te6edf3value Tff7b72= Tff7b72false
Te6edf3allowNodeDbWritesTb4b4b4.Te6edf3value Tff7b72= Tff7b72false
Te6edf3myNodeNumTb4b4b4.Te6edf3value Tff7b72= Tff7b72null
Tb4b4b4}

Tff7b72override Tff7b72fun Td2a8ffgetMyNodeInfoTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3MyNodeInfo? Tb4b4b4{
Tff7b72val Te6edf3mi Tff7b72= Te6edf3nodeRepositoryTb4b4b4.Te6edf3myNodeInfoTb4b4b4.Te6edf3value Tff7b72?: Tff7b72return Tff7b72null
Tff7b72val Te6edf3myNode Tff7b72= Te6edf3_nodeDBbyNodeNumTb4b4b4.Te6edf3valueTff7b72[Te6edf3miTb4b4b4.Te6edf3myNodeNumTff7b72]
Tff7b72return Te6edf3MyNodeInfoTb4b4b4(
Te6edf3myNodeNum Tff7b72= Te6edf3miTb4b4b4.Te6edf3myNodeNumTb4b4b4,
Te6edf3hasGPS Tff7b72= Tb4b4b4(Te6edf3myNodeTff7b72?.Te6edf3positionTff7b72?.Te6edf3latitude_i Tff7b72?: T79c0ff0Tb4b4b4) Tff7b72!Tff7b72= T79c0ff0Tb4b4b4,
Te6edf3model Tff7b72= Te6edf3miTb4b4b4.Te6edf3model Tff7b72?: Te6edf3myNodeTff7b72?.Te6edf3userTff7b72?.Te6edf3hw_modelTff7b72?.Te6edf3nameTb4b4b4,
Te6edf3firmwareVersion Tff7b72= Te6edf3miTb4b4b4.Te6edf3firmwareVersionTb4b4b4,
Te6edf3couldUpdate Tff7b72= Te6edf3miTb4b4b4.Te6edf3couldUpdateTb4b4b4,
Te6edf3shouldUpdate Tff7b72= Te6edf3miTb4b4b4.Te6edf3shouldUpdateTb4b4b4,
Te6edf3currentPacketId Tff7b72= Te6edf3miTb4b4b4.Te6edf3currentPacketIdTb4b4b4,
Te6edf3messageTimeoutMsec Tff7b72= Te6edf3miTb4b4b4.Te6edf3messageTimeoutMsecTb4b4b4,
Te6edf3minAppVersion Tff7b72= Te6edf3miTb4b4b4.Te6edf3minAppVersionTb4b4b4,
Te6edf3maxChannels Tff7b72= Te6edf3miTb4b4b4.Te6edf3maxChannelsTb4b4b4,
Te6edf3hasWifi Tff7b72= Te6edf3miTb4b4b4.Te6edf3hasWifiTb4b4b4,
Te6edf3channelUtilization Tff7b72= T79c0ff0fTb4b4b4,
Te6edf3airUtilTx Tff7b72= T79c0ff0fTb4b4b4,
Te6edf3deviceId Tff7b72= Te6edf3miTb4b4b4.Te6edf3deviceId Tff7b72?: Te6edf3myNodeTff7b72?.Te6edf3userTff7b72?.Te6edf3idTb4b4b4,
Tb4b4b4)
Tb4b4b4}

Tff7b72override Tff7b72fun Td2a8ffgetMyIdTb4b4b4(Tb4b4b4)Tb4b4b4: Tffa657String Tb4b4b4{
Tff7b72val Te6edf3num Tff7b72= Te6edf3myNodeNumTb4b4b4.Te6edf3value Tff7b72?: Te6edf3nodeRepositoryTb4b4b4.Te6edf3myNodeInfoTb4b4b4.Te6edf3valueTff7b72?.Te6edf3myNodeNum Tff7b72?: Tff7b72return Ta5d6ff"Ta5d6ff"
Tff7b72return Te6edf3_nodeDBbyNodeNumTb4b4b4.Te6edf3valueTff7b72[Te6edf3numTff7b72]Tff7b72?.Te6edf3userTff7b72?.Te6edf3id Tff7b72?: Ta5d6ff"Ta5d6ff"
Tb4b4b4}

Tff7b72override Tff7b72fun Td2a8ffgetNodesTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3ListTff7b72<Te6edf3NodeInfoTff7b72> Tff7b72= Te6edf3_nodeDBbyNodeNumTb4b4b4.Te6edf3valueTb4b4b4.Te6edf3valuesTb4b4b4.Te6edf3map Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3toNodeInfoTb4b4b4(Tb4b4b4) Tb4b4b4}

Tff7b72override Tff7b72fun Td2a8ffremoveByNodenumTb4b4b4(Te6edf3nodeNumTb4b4b4: Tffa657IntTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3removed Tff7b72= Te6edf3atomicTff7b72<Te6edf3Node?Tff7b72>Tb4b4b4(Tff7b72nullTb4b4b4)
Te6edf3_nodeDBbyNodeNumTb4b4b4.Te6edf3update Tb4b4b4{ Te6edf3map Tff7b72-Tff7b72>
Tff7b72val Te6edf3node Tff7b72= Te6edf3mapTff7b72[Te6edf3nodeNumTff7b72]
Te6edf3removedTb4b4b4.Te6edf3value Tff7b72= Te6edf3node
Te6edf3mapTb4b4b4.Te6edf3removeTb4b4b4(Te6edf3nodeNumTb4b4b4)
Tb4b4b4}
Te6edf3removedTb4b4b4.Te6edf3valueTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3node Tff7b72-Tff7b72> Te6edf3_nodeDBbyIDTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3removeTb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3userTb4b4b4.Te6edf3idTb4b4b4) Tb4b4b4} Tb4b4b4}
Tb4b4b4}

Tff7b72internal Tff7b72fun Td2a8ffgetOrCreateNodeTb4b4b4(Te6edf3nTb4b4b4: Tffa657IntTb4b4b4, Te6edf3channelTb4b4b4: Tffa657Int Tff7b72= T79c0ff0Tb4b4b4)Tb4b4b4: Te6edf3Node Tff7b72= Te6edf3_nodeDBbyNodeNumTb4b4b4.Te6edf3valueTff7b72[Te6edf3nTff7b72]
Tff7b72?: Te6edf3run Tb4b4b4{
Tff7b72val Te6edf3userId Tff7b72= Te6edf3DataPacketTb4b4b4.Te6edf3nodeNumToDefaultIdTb4b4b4(Te6edf3nTb4b4b4)
Tff7b72val Te6edf3defaultUser Tff7b72=
Te6edf3UserTb4b4b4(
Te6edf3id Tff7b72= Te6edf3userIdTb4b4b4,
Te6edf3long_name Tff7b72= Ta5d6ff"Ta5d6ffMeshtastic Tffd700${Te6edf3userIdTb4b4b4.Te6edf3takeLastTb4b4b4(Te6edf3n Tff7b72= T79c0ff4Tb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4,
Te6edf3short_name Tff7b72= Te6edf3userIdTb4b4b4.Te6edf3takeLastTb4b4b4(Te6edf3n Tff7b72= T79c0ff4Tb4b4b4)Tb4b4b4,
Te6edf3hw_model Tff7b72= Te6edf3HardwareModelTb4b4b4.Te6edf3UNSETTb4b4b4,
Tb4b4b4)

Te6edf3NodeTb4b4b4(Te6edf3num Tff7b72= Te6edf3nTb4b4b4, Te6edf3user Tff7b72= Te6edf3defaultUserTb4b4b4, Te6edf3channel Tff7b72= Te6edf3channelTb4b4b4)
Tb4b4b4}

Tff7b72override Tff7b72fun Td2a8ffupdateNodeTb4b4b4(Te6edf3nodeNumTb4b4b4: Tffa657IntTb4b4b4, Te6edf3withBroadcastTb4b4b4: Tffa657BooleanTb4b4b4, Te6edf3channelTb4b4b4: Tffa657IntTb4b4b4, Te6edf3transformTb4b4b4: Tb4b4b4(Te6edf3NodeTb4b4b4) Tff7b72-Tff7b72> Te6edf3NodeTb4b4b4) Tb4b4b4{
T8b949e// Perform read + transform inside update{} to ensure atomicity.
T8b949e// Without this, concurrent calls for the same nodeNum could read the same snapshot
T8b949e// and the last writer would silently overwrite the other's changes.
Tff7b72var Te6edf3nextTb4b4b4: Te6edf3Node? Tff7b72= Tff7b72null
Te6edf3_nodeDBbyNodeNumTb4b4b4.Te6edf3update Tb4b4b4{ Te6edf3map Tff7b72-Tff7b72>
Tff7b72val Te6edf3current Tff7b72= Te6edf3mapTff7b72[Te6edf3nodeNumTff7b72] Tff7b72?: Te6edf3getOrCreateNodeTb4b4b4(Te6edf3nodeNumTb4b4b4, Te6edf3channelTb4b4b4)
Tff7b72val Te6edf3transformed Tff7b72= Te6edf3transformTb4b4b4(Te6edf3currentTb4b4b4)
Te6edf3next Tff7b72= Te6edf3transformed
Te6edf3mapTb4b4b4.Te6edf3putTb4b4b4(Te6edf3nodeNumTb4b4b4, Te6edf3transformedTb4b4b4)
Tb4b4b4}
Tff7b72val Te6edf3result Tff7b72= Te6edf3next Tff7b72?: Tff7b72return
Tff7b72if Tb4b4b4(Te6edf3resultTb4b4b4.Te6edf3userTb4b4b4.Te6edf3idTb4b4b4.Te6edf3isNotEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3_nodeDBbyIDTb4b4b4.Te6edf3update Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3putTb4b4b4(Te6edf3resultTb4b4b4.Te6edf3userTb4b4b4.Te6edf3idTb4b4b4, Te6edf3resultTb4b4b4) Tb4b4b4}
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3resultTb4b4b4.Te6edf3userTb4b4b4.Te6edf3idTb4b4b4.Te6edf3isNotEmptyTb4b4b4(Tb4b4b4) Tff7b72&Tff7b72& Te6edf3isNodeDbReadyTb4b4b4.Te6edf3valueTb4b4b4) Tb4b4b4{
Te6edf3scopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{ Te6edf3nodeRepositoryTb4b4b4.Te6edf3upsertTb4b4b4(Te6edf3resultTb4b4b4) Tb4b4b4}
Tb4b4b4}

Tff7b72if Tb4b4b4(Te6edf3withBroadcastTb4b4b4) Tb4b4b4{
Te6edf3serviceBroadcastsTb4b4b4.Te6edf3broadcastNodeChangeTb4b4b4(Te6edf3resultTb4b4b4)
Tb4b4b4}
Tb4b4b4}

Tff7b72override Tff7b72fun Td2a8ffhandleReceivedUserTb4b4b4(Te6edf3fromNumTb4b4b4: Tffa657IntTb4b4b4, Te6edf3pTb4b4b4: Te6edf3UserTb4b4b4, Te6edf3channelTb4b4b4: Tffa657IntTb4b4b4, Te6edf3manuallyVerifiedTb4b4b4: Tffa657BooleanTb4b4b4) Tb4b4b4{
Te6edf3updateNodeTb4b4b4(Te6edf3fromNumTb4b4b4) Tb4b4b4{ Te6edf3node Tff7b72-Tff7b72>
Tff7b72val Te6edf3newNode Tff7b72= Tb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3isUnknownUser Tff7b72&Tff7b72& Te6edf3pTb4b4b4.Te6edf3hw_model Tff7b72!Tff7b72= Te6edf3HardwareModelTb4b4b4.Te6edf3UNSETTb4b4b4)
Tff7b72val Te6edf3shouldPreserve Tff7b72= Te6edf3shouldPreserveExistingUserTb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3userTb4b4b4, Te6edf3pTb4b4b4)

Tff7b72val Te6edf3next Tff7b72=
Tff7b72if Tb4b4b4(Te6edf3shouldPreserveTb4b4b4) Tb4b4b4{
Te6edf3nodeTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3channel Tff7b72= Te6edf3channelTb4b4b4, Te6edf3manuallyVerified Tff7b72= Te6edf3manuallyVerifiedTb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72val Te6edf3keyMatch Tff7b72= Tff7b72!Te6edf3nodeTb4b4b4.Te6edf3hasPKC Tff7b72|Tff7b72| Te6edf3nodeTb4b4b4.Te6edf3userTb4b4b4.Te6edf3public_key Tff7b72=Tff7b72= Te6edf3pTb4b4b4.Te6edf3public_key
Tff7b72val Te6edf3newUser Tff7b72= Tff7b72if Tb4b4b4(Te6edf3keyMatchTb4b4b4) Te6edf3p Tff7b72else Te6edf3pTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3public_key Tff7b72= Te6edf3ByteStringTb4b4b4.Te6edf3EMPTYTb4b4b4)
Te6edf3nodeTb4b4b4.Te6edf3copyTb4b4b4(
Te6edf3user Tff7b72= Te6edf3newUserTb4b4b4,
Te6edf3publicKey Tff7b72= Te6edf3newUserTb4b4b4.Te6edf3public_keyTb4b4b4,
Te6edf3channel Tff7b72= Te6edf3channelTb4b4b4,
Te6edf3manuallyVerified Tff7b72= Te6edf3manuallyVerifiedTb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3newNode Tff7b72&Tff7b72& Tff7b72!Te6edf3shouldPreserveTb4b4b4) Tb4b4b4{
Te6edf3scopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{
Te6edf3notificationManagerTb4b4b4.Te6edf3dispatchTb4b4b4(
Te6edf3NotificationTb4b4b4(
Te6edf3title Tff7b72= Te6edf3getStringSuspendTb4b4b4(Te6edf3ResTb4b4b4.Te6edf3stringTb4b4b4.Te6edf3new_node_seenTb4b4b4, Te6edf3nextTb4b4b4.Te6edf3userTb4b4b4.Te6edf3short_nameTb4b4b4)Tb4b4b4,
Te6edf3message Tff7b72= Te6edf3nextTb4b4b4.Te6edf3userTb4b4b4.Te6edf3long_nameTb4b4b4,
Te6edf3category Tff7b72= Te6edf3NotificationTb4b4b4.Te6edf3CategoryTb4b4b4.Te6edf3NodeEventTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Te6edf3next
Tb4b4b4}
Tb4b4b4}

Tff7b72override Tff7b72fun Td2a8ffhandleReceivedPositionTb4b4b4(Te6edf3fromNumTb4b4b4: Tffa657IntTb4b4b4, Te6edf3myNodeNumTb4b4b4: Tffa657IntTb4b4b4, Te6edf3pTb4b4b4: Te6edf3ProtoPositionTb4b4b4, Te6edf3defaultTimeTb4b4b4: Tffa657LongTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3isZeroPos Tff7b72= Tb4b4b4(Te6edf3pTb4b4b4.Te6edf3latitude_i Tff7b72?: T79c0ff0Tb4b4b4) Tff7b72=Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Tb4b4b4(Te6edf3pTb4b4b4.Te6edf3longitude_i Tff7b72?: T79c0ff0Tb4b4b4) Tff7b72=Tff7b72= T79c0ff0
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffComplexConditionTa5d6ff"Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3myNodeNum Tff7b72=Tff7b72= Te6edf3fromNum Tff7b72&Tff7b72& Te6edf3isZeroPos Tff7b72&Tff7b72& Te6edf3pTb4b4b4.Te6edf3sats_in_view Tff7b72=Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Te6edf3pTb4b4b4.Te6edf3time Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3LoggerTb4b4b4.Te6edf3d Tb4b4b4{ Ta5d6ff"Ta5d6ffIgnoring empty position update for the local nodeTa5d6ff" Tb4b4b4}
Tff7b72return
Tb4b4b4}

Te6edf3updateNodeTb4b4b4(Te6edf3fromNumTb4b4b4) Tb4b4b4{ Te6edf3node Tff7b72-Tff7b72>
Tff7b72val Te6edf3posTime Tff7b72= Tff7b72if Tb4b4b4(Te6edf3pTb4b4b4.Te6edf3time Tff7b72!Tff7b72= T79c0ff0Tb4b4b4) Te6edf3pTb4b4b4.Te6edf3time Tff7b72else Tb4b4b4(Te6edf3defaultTime Tff7b72/ Te6edf3TIME_MS_TO_STb4b4b4)Tb4b4b4.Te6edf3toIntTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3newLastHeard Tff7b72= Te6edf3maxOfTb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3lastHeardTb4b4b4, Te6edf3posTimeTb4b4b4)

Tff7b72val Te6edf3newPos Tff7b72=
Tff7b72if Tb4b4b4(Te6edf3isZeroPosTb4b4b4) Tb4b4b4{
Te6edf3pTb4b4b4.Te6edf3copyTb4b4b4(
Te6edf3time Tff7b72= Te6edf3posTimeTb4b4b4,
Te6edf3latitude_i Tff7b72= Te6edf3nodeTb4b4b4.Te6edf3positionTb4b4b4.Te6edf3latitude_iTb4b4b4,
Te6edf3longitude_i Tff7b72= Te6edf3nodeTb4b4b4.Te6edf3positionTb4b4b4.Te6edf3longitude_iTb4b4b4,
Te6edf3altitude Tff7b72= Te6edf3pTb4b4b4.Te6edf3altitude Tff7b72?: Te6edf3nodeTb4b4b4.Te6edf3positionTb4b4b4.Te6edf3altitudeTb4b4b4,
Te6edf3sats_in_view Tff7b72= Te6edf3pTb4b4b4.Te6edf3sats_in_viewTb4b4b4,
Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3pTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3time Tff7b72= Te6edf3posTimeTb4b4b4)
Tb4b4b4}

Te6edf3nodeTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3position Tff7b72= Te6edf3newPosTb4b4b4, Te6edf3lastHeard Tff7b72= Te6edf3newLastHeardTb4b4b4)
Tb4b4b4}
Tb4b4b4}

Tff7b72override Tff7b72fun Td2a8ffhandleReceivedTelemetryTb4b4b4(Te6edf3fromNumTb4b4b4: Tffa657IntTb4b4b4, Te6edf3telemetryTb4b4b4: Te6edf3TelemetryTb4b4b4) Tb4b4b4{
Te6edf3updateNodeTb4b4b4(Te6edf3fromNumTb4b4b4) Tb4b4b4{ Te6edf3node Tff7b72-Tff7b72>
Tff7b72var Te6edf3nextNode Tff7b72= Te6edf3node
Te6edf3telemetryTb4b4b4.Te6edf3device_metricsTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3nextNode Tff7b72= Te6edf3nextNodeTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3deviceMetrics Tff7b72= Tffa657itTb4b4b4) Tb4b4b4}
Te6edf3telemetryTb4b4b4.Te6edf3environment_metricsTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3nextNode Tff7b72= Te6edf3nextNodeTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3environmentMetrics Tff7b72= Tffa657itTb4b4b4) Tb4b4b4}
Te6edf3telemetryTb4b4b4.Te6edf3power_metricsTff7b72?.Te6edf3let Tb4b4b4{ Te6edf3nextNode Tff7b72= Te6edf3nextNodeTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3powerMetrics Tff7b72= Tffa657itTb4b4b4) Tb4b4b4}
Tff7b72val Te6edf3telemetryTime Tff7b72= Tff7b72if Tb4b4b4(Te6edf3telemetryTb4b4b4.Te6edf3time Tff7b72!Tff7b72= T79c0ff0Tb4b4b4) Te6edf3telemetryTb4b4b4.Te6edf3time Tff7b72else Te6edf3nodeTb4b4b4.Te6edf3lastHeard
Tff7b72val Te6edf3newLastHeard Tff7b72= Te6edf3maxOfTb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3lastHeardTb4b4b4, Te6edf3telemetryTimeTb4b4b4)
Te6edf3nextNodeTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3lastHeard Tff7b72= Te6edf3newLastHeardTb4b4b4)
Tb4b4b4}
Tb4b4b4}

Tff7b72override Tff7b72fun Td2a8ffhandleReceivedPaxcounterTb4b4b4(Te6edf3fromNumTb4b4b4: Tffa657IntTb4b4b4, Te6edf3pTb4b4b4: Te6edf3PaxcountTb4b4b4) Tb4b4b4{
Te6edf3updateNodeTb4b4b4(Te6edf3fromNumTb4b4b4) Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3paxcounter Tff7b72= Te6edf3pTb4b4b4) Tb4b4b4}
Tb4b4b4}

Tff7b72override Tff7b72fun Td2a8ffhandleReceivedNodeStatusTb4b4b4(Te6edf3fromNumTb4b4b4: Tffa657IntTb4b4b4, Te6edf3sTb4b4b4: Te6edf3StatusMessageTb4b4b4) Tb4b4b4{
Te6edf3updateNodeStatusTb4b4b4(Te6edf3fromNumTb4b4b4, Te6edf3sTb4b4b4.Te6edf3statusTb4b4b4)
Tb4b4b4}

Tff7b72override Tff7b72fun Td2a8ffupdateNodeStatusTb4b4b4(Te6edf3nodeNumTb4b4b4: Tffa657IntTb4b4b4, Te6edf3statusTb4b4b4: Tffa657String?Tb4b4b4) Tb4b4b4{
Te6edf3updateNodeTb4b4b4(Te6edf3nodeNumTb4b4b4) Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3nodeStatus Tff7b72= Te6edf3statusTff7b72?.Te6edf3takeIf Tb4b4b4{ Te6edf3s Tff7b72-Tff7b72> Te6edf3sTb4b4b4.Te6edf3isNotEmptyTb4b4b4(Tb4b4b4) Tb4b4b4}Tb4b4b4) Tb4b4b4}
Tb4b4b4}

Tff7b72override Tff7b72fun Td2a8ffinstallNodeInfoTb4b4b4(Te6edf3infoTb4b4b4: Te6edf3ProtoNodeInfoTb4b4b4, Te6edf3withBroadcastTb4b4b4: Tffa657BooleanTb4b4b4) Tb4b4b4{
Te6edf3updateNodeTb4b4b4(Te6edf3infoTb4b4b4.Te6edf3numTb4b4b4, Te6edf3withBroadcast Tff7b72= Te6edf3withBroadcastTb4b4b4) Tb4b4b4{ Te6edf3node Tff7b72-Tff7b72>
Tff7b72var Te6edf3next Tff7b72= Te6edf3node
Tff7b72val Te6edf3user Tff7b72= Te6edf3infoTb4b4b4.Te6edf3user
Tff7b72if Tb4b4b4(Te6edf3user Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3shouldPreserveExistingUserTb4b4b4(Te6edf3nodeTb4b4b4.Te6edf3userTb4b4b4, Te6edf3userTb4b4b4)Tb4b4b4) Tb4b4b4{
T8b949e// keep existing names
Tb4b4b4} Tff7b72else Tb4b4b4{
Tff7b72var Te6edf3newUser Tff7b72=
Te6edf3userTb4b4b4.Te6edf3let Tb4b4b4{ Tff7b72if Tb4b4b4(Tffa657itTb4b4b4.Te6edf3is_licensed Tff7b72=Tff7b72= Tff7b72trueTb4b4b4) Tffa657itTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3public_key Tff7b72= Te6edf3ByteStringTb4b4b4.Te6edf3EMPTYTb4b4b4) Tff7b72else Tffa657it Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3infoTb4b4b4.Te6edf3via_mqtt Tff7b72&Tff7b72& Tff7b72!Te6edf3newUserTb4b4b4.Te6edf3long_nameTb4b4b4.Te6edf3endsWithTb4b4b4(Ta5d6ff"Ta5d6ff (MQTT)Ta5d6ff"Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3newUser Tff7b72= Te6edf3newUserTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3long_name Tff7b72= Ta5d6ff"Tffd700${Te6edf3newUserTb4b4b4.Te6edf3long_nameTffd700}Ta5d6ff (MQTT)Ta5d6ff"Tb4b4b4)
Tb4b4b4}
Te6edf3next Tff7b72= Te6edf3nextTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3user Tff7b72= Te6edf3newUserTb4b4b4, Te6edf3publicKey Tff7b72= Te6edf3newUserTb4b4b4.Te6edf3public_keyTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72val Te6edf3position Tff7b72= Te6edf3infoTb4b4b4.Te6edf3position
Tff7b72if Tb4b4b4(Te6edf3position Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Tb4b4b4{
Te6edf3next Tff7b72= Te6edf3nextTb4b4b4.Te6edf3copyTb4b4b4(Te6edf3position Tff7b72= Te6edf3positionTb4b4b4)
Tb4b4b4}
Te6edf3next Tff7b72=
Te6edf3nextTb4b4b4.Te6edf3copyTb4b4b4(
Te6edf3lastHeard Tff7b72= Te6edf3infoTb4b4b4.Te6edf3last_heardTb4b4b4,
Te6edf3deviceMetrics Tff7b72= Te6edf3infoTb4b4b4.Te6edf3device_metrics Tff7b72?: Te6edf3nextTb4b4b4.Te6edf3deviceMetricsTb4b4b4,
Te6edf3channel Tff7b72= Te6edf3infoTb4b4b4.Te6edf3channelTb4b4b4,
Te6edf3viaMqtt Tff7b72= Te6edf3infoTb4b4b4.Te6edf3via_mqttTb4b4b4,
Te6edf3hopsAway Tff7b72= Te6edf3infoTb4b4b4.Te6edf3hops_away Tff7b72?: Tff7b72-T79c0ff1Tb4b4b4,
Te6edf3isFavorite Tff7b72= Te6edf3infoTb4b4b4.Te6edf3is_favoriteTb4b4b4,
Te6edf3isIgnored Tff7b72= Te6edf3infoTb4b4b4.Te6edf3is_ignoredTb4b4b4,
Te6edf3isMuted Tff7b72= Te6edf3infoTb4b4b4.Te6edf3is_mutedTb4b4b4,
Tb4b4b4)
Te6edf3next
Tb4b4b4}
Tb4b4b4}

Tff7b72override Tff7b72fun Td2a8ffinsertMetadataTb4b4b4(Te6edf3nodeNumTb4b4b4: Tffa657IntTb4b4b4, Te6edf3metadataTb4b4b4: Te6edf3DeviceMetadataTb4b4b4) Tb4b4b4{
Te6edf3scopeTb4b4b4.Te6edf3handledLaunch Tb4b4b4{ Te6edf3nodeRepositoryTb4b4b4.Te6edf3insertMetadataTb4b4b4(Te6edf3nodeNumTb4b4b4, Te6edf3metadataTb4b4b4) Tb4b4b4}
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffshouldPreserveExistingUserTb4b4b4(Te6edf3existingTb4b4b4: Te6edf3UserTb4b4b4, Te6edf3incomingTb4b4b4: Te6edf3UserTb4b4b4)Tb4b4b4: Tffa657Boolean Tb4b4b4{
Tff7b72val Te6edf3isDefaultName Tff7b72= Tb4b4b4(Te6edf3incomingTb4b4b4.Te6edf3long_nameTb4b4b4)Tb4b4b4.Te6edf3matchesTb4b4b4(Te6edf3RegexTb4b4b4(Ta5d6ff"Ta5d6ff^Meshtastic [0-9a-fA-F]{4}$Ta5d6ff"Tb4b4b4)Tb4b4b4)
Tff7b72val Te6edf3isDefaultHwModel Tff7b72= Te6edf3incomingTb4b4b4.Te6edf3hw_model Tff7b72=Tff7b72= Te6edf3HardwareModelTb4b4b4.Te6edf3UNSET
Tff7b72val Te6edf3hasExistingUser Tff7b72= Tb4b4b4(Te6edf3existingTb4b4b4.Te6edf3idTb4b4b4)Tb4b4b4.Te6edf3isNotEmptyTb4b4b4(Tb4b4b4) Tff7b72&Tff7b72& Te6edf3existingTb4b4b4.Te6edf3hw_model Tff7b72!Tff7b72= Te6edf3HardwareModelTb4b4b4.Te6edf3UNSET
Tff7b72return Te6edf3hasExistingUser Tff7b72&Tff7b72& Te6edf3isDefaultName Tff7b72&Tff7b72& Te6edf3isDefaultHwModel
Tb4b4b4}

Tff7b72override Tff7b72fun Td2a8fftoNodeIDTb4b4b4(Te6edf3nodeNumTb4b4b4: Tffa657IntTb4b4b4)Tb4b4b4: Tffa657String Tff7b72= Tff7b72if Tb4b4b4(Te6edf3nodeNum Tff7b72=Tff7b72= Te6edf3DataPacketTb4b4b4.Te6edf3NODENUM_BROADCASTTb4b4b4) Tb4b4b4{
Te6edf3DataPacketTb4b4b4.Te6edf3ID_BROADCAST
Tb4b4b4} Tff7b72else Tb4b4b4{
Te6edf3_nodeDBbyNodeNumTb4b4b4.Te6edf3valueTff7b72[Te6edf3nodeNumTff7b72]Tff7b72?.Te6edf3userTff7b72?.Te6edf3id Tff7b72?: Te6edf3DataPacketTb4b4b4.Te6edf3nodeNumToDefaultIdTb4b4b4(Te6edf3nodeNumTb4b4b4)
Tb4b4b4}

Tff7b72private Tff7b72fun Te6edf3NodeTb4b4b4.Td2a8fftoNodeInfoTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3NodeInfo Tff7b72= Te6edf3NodeInfoTb4b4b4(
Te6edf3num Tff7b72= Te6edf3numTb4b4b4,
Te6edf3user Tff7b72=
Te6edf3MeshUserTb4b4b4(
Te6edf3id Tff7b72= Te6edf3userTb4b4b4.Te6edf3idTb4b4b4,
Te6edf3longName Tff7b72= Te6edf3userTb4b4b4.Te6edf3long_nameTb4b4b4,
Te6edf3shortName Tff7b72= Te6edf3userTb4b4b4.Te6edf3short_nameTb4b4b4,
Te6edf3hwModel Tff7b72= Te6edf3userTb4b4b4.Te6edf3hw_modelTb4b4b4,
Te6edf3role Tff7b72= Te6edf3userTb4b4b4.Te6edf3roleTb4b4b4.Te6edf3valueTb4b4b4,
Tb4b4b4)Tb4b4b4,
Te6edf3position Tff7b72=
Te6edf3PositionTb4b4b4(
Te6edf3latitude Tff7b72= Te6edf3latitudeTb4b4b4,
Te6edf3longitude Tff7b72= Te6edf3longitudeTb4b4b4,
Te6edf3altitude Tff7b72= Te6edf3positionTb4b4b4.Te6edf3altitude Tff7b72?: T79c0ff0Tb4b4b4,
Te6edf3time Tff7b72= Te6edf3positionTb4b4b4.Te6edf3timeTb4b4b4,
Te6edf3satellitesInView Tff7b72= Te6edf3positionTb4b4b4.Te6edf3sats_in_viewTb4b4b4,
Te6edf3groundSpeed Tff7b72= Te6edf3positionTb4b4b4.Te6edf3ground_speed Tff7b72?: T79c0ff0Tb4b4b4,
Te6edf3groundTrack Tff7b72= Te6edf3positionTb4b4b4.Te6edf3ground_track Tff7b72?: T79c0ff0Tb4b4b4,
Te6edf3precisionBits Tff7b72= Te6edf3positionTb4b4b4.Te6edf3precision_bitsTb4b4b4,
Tb4b4b4)
Tb4b4b4.Te6edf3takeIf Tb4b4b4{ Te6edf3latitude Tff7b72!Tff7b72= T79c0ff0.0 Tff7b72|Tff7b72| Te6edf3longitude Tff7b72!Tff7b72= T79c0ff0.0 Tb4b4b4}Tb4b4b4,
Te6edf3snr Tff7b72= Te6edf3snrTb4b4b4,
Te6edf3rssi Tff7b72= Te6edf3rssiTb4b4b4,
Te6edf3lastHeard Tff7b72= Te6edf3lastHeardTb4b4b4,
Te6edf3deviceMetrics Tff7b72=
Te6edf3DeviceMetricsTb4b4b4(
Te6edf3batteryLevel Tff7b72= Te6edf3deviceMetricsTb4b4b4.Te6edf3battery_level Tff7b72?: T79c0ff0Tb4b4b4,
Te6edf3voltage Tff7b72= Te6edf3deviceMetricsTb4b4b4.Te6edf3voltage Tff7b72?: T79c0ff0fTb4b4b4,
Te6edf3channelUtilization Tff7b72= Te6edf3deviceMetricsTb4b4b4.Te6edf3channel_utilization Tff7b72?: T79c0ff0fTb4b4b4,
Te6edf3airUtilTx Tff7b72= Te6edf3deviceMetricsTb4b4b4.Te6edf3air_util_tx Tff7b72?: T79c0ff0fTb4b4b4,
Te6edf3uptimeSeconds Tff7b72= Te6edf3deviceMetricsTb4b4b4.Te6edf3uptime_seconds Tff7b72?: T79c0ff0Tb4b4b4,
Tb4b4b4)Tb4b4b4,
Te6edf3channel Tff7b72= Te6edf3channelTb4b4b4,
Te6edf3environmentMetrics Tff7b72= Te6edf3EnvironmentMetricsTb4b4b4.Te6edf3fromTelemetryProtoTb4b4b4(Te6edf3environmentMetricsTb4b4b4, T79c0ff0Tb4b4b4)Tb4b4b4,
Te6edf3hopsAway Tff7b72= Te6edf3hopsAwayTb4b4b4,
Te6edf3nodeStatus Tff7b72= Te6edf3nodeStatusTb4b4b4,
Tb4b4b4)
Tb4b4b4}

Served by rngit 1.5.0 - Generated in 0.11s